using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RotationUI
{
    public class AllPointAndSize : Source
    {
        private int BoxWidth { get; set; }
        private int BoxHeight { get; set; }
        private double MaxWidth { get; set; }
        private double MinWidth { get; set; }
        private double MaxHeight { get; set; }
        public double MinHeight { get; set; }
        /// <summary>
        /// 显示数量
        /// </summary>
        private int ShowCount { get; set; }
        /// <summary>
        /// 水平边距
        /// </summary>
        private int LevelMargin { get; set; }
        /// <summary>
        /// 台阶宽
        /// </summary>
        private double StepWidth { get; set; }
        /// <summary>
        /// 源图
        /// </summary>
        Bitmap sourceBitmap { get; set; }

        private PointData[] PointDatas { get; set; }
        /// <summary>
        /// 先添加图源再初始化
        /// </summary>
        public void Init(int showCount, int levelMargin, int boxWidth, int boxHeight, double maxWidth, double maxHeight, double minWidth, double minHeight, int RunTime, int RunInterval = 20)
        {
            BoxWidth = boxWidth;
            BoxHeight = boxHeight;
            MaxWidth = maxWidth;
            MaxHeight = maxHeight;
            MinWidth = minWidth;
            MinHeight = minHeight;
            ShowCount = showCount;
            LevelMargin = levelMargin;
            this.RunInterval = RunInterval;
            this.RunTime = RunTime;
            StepsNumber = ShowCount / 2 + 1;
            StepWidth = (BoxWidth / 2 - MaxWidth / 2 - LevelMargin) / (ShowCount / 2);
            RunCount = RunTime / RunInterval;
            if (RunCount % 2 == 0)
            {
                RunCount++;
                this.RunTime += RunInterval;
            }
            var AllCount = RunCount + RunCount / (bitmapData.Count - 1);
            PointDatas = new PointData[AllCount];
            PointDatas[0] = new PointData()
            {
                ID = 0,
                SubType = 0,
                ShowOrder = 0,
                Point = new BitmapPoint(LevelMargin, (boxHeight - minHeight) / 2),
                Size = new BitmapSize(minWidth, minHeight),
                PointType = 0
            };
            int midpoint = RunCount / 2 + 1;
            PointDatas[midpoint] = new PointData()
            {
                ID = midpoint,
                SubType = 1,
                ShowOrder = midpoint,
                Point = new BitmapPoint((BoxWidth - MaxWidth) / 2, (BoxHeight - MaxHeight) / 2),
                Size = new BitmapSize(MaxWidth, MaxHeight),
                PointType = 0
            };
            int endPoint = RunCount - 1;
            PointDatas[endPoint] = new PointData()
            {
                ID = endPoint,
                SubType = 2,
                ShowOrder = 0,
                Point = new BitmapPoint(BoxWidth - LevelMargin, (BoxHeight - MinHeight) / 2),
                Size = new BitmapSize(MinWidth, MinHeight),
                PointType = 1
            };
            //PointDatas[RunCount] = new PointData()
            //{
            //    ID = RunCount,
            //    SubType = 2,
            //    ShowOrder = -1,
            //    Point = new BitmapPoint(BoxWidth - LevelMargin, (BoxHeight - MinHeight) / 2),
            //    Size = new BitmapSize(MinWidth, MinHeight),
            //    PointType = 1
            //};
            PointDatas[PointDatas.Length - 1] = new PointData()
            {
                ID = PointDatas.Length - 1,
                SubType = 2,
                ShowOrder = -1,
                Point = new BitmapPoint((MinWidth + LevelMargin), (BoxHeight - MinHeight) / 2),
                Size = new BitmapSize(MinWidth, MinHeight),
                PointType = 1
            };

            for (int i = 0; i < PointDatas.Length; i++)
            {
                if (PointDatas[i] == null)
                {
                    PointDatas[i] = new PointData()
                    {
                        ID = i,
                    };
                    PointDatas[i].SubType = PointDatas[i - 1].SubType;
                    PointDatas[i].ShowOrder = i > midpoint ? RunCount - i : i;
                    PointDatas[i].Size = SubSize(i > RunCount ? RunCount : i, midpoint);
                    if (i > midpoint && i < RunCount)
                    {
                        PointDatas[i].PointType = 1;
                        PointDatas[i].Point = SubPoint(PointDatas[i].SubType, i - midpoint, RunCount - 1- midpoint, PointDatas[midpoint].Point, PointDatas[RunCount - 1].Point);
                    }
                    else if (i <= midpoint)
                    {
                        PointDatas[i].PointType = 0;
                        PointDatas[i].Point = SubPoint(PointDatas[i].SubType, i, midpoint+1, PointDatas[midpoint].Point, PointDatas[0].Point);
                    }
                    else
                    {
                        PointDatas[i].PointType = 1;
                        PointDatas[i].Point = SubPoint(PointDatas[i].SubType, i - RunCount+1, (RunCount-1) / (bitmapData.Count - 1), PointDatas[RunCount-1].Point, PointDatas[PointDatas.Length - 1].Point);
                    }
                }
            }

            for (int i = 0; i < bitmapData.Count; i++)
            {
                bitmapData[i].PointID = RunCount / (bitmapData.Count - 1) * i;
            }
        }
        public PointData[] GetPoint()
        {
            return PointDatas;
        }
        private BitmapSize SubSize(int order, int MaximumStep)
        {
            if (order > MaximumStep)
            {
                order = MaximumStep * 2 - order;
            }
            BitmapSize size = new BitmapSize();
            size.Width = (MaxWidth - MinWidth) / MaximumStep * order + MinWidth;
            size.Height = (MaxHeight - MinHeight) / MaximumStep * order + MinHeight;
            return size;
        }

        private BitmapPoint SubPoint(int SubType, int order, int MaximumStep, BitmapPoint max, BitmapPoint min)
        {
            BitmapPoint point = new BitmapPoint();
            if (SubType == 0)
            {
                point.X = (max.X - min.X) / MaximumStep * order + min.X;
                point.Y = (max.Y - min.Y) / MaximumStep * order + min.Y;
            }
            if (SubType == 1)
            {
                point.X = (min.X - max.X - MaxWidth) / MaximumStep * order + max.X + MaxWidth;
                point.Y = (min.Y - max.Y) / MaximumStep * order + max.Y;
            }
            if (SubType == 2)
            {
                point.X = max.X - (max.X - min.X) / MaximumStep * order;
                point.Y = min.Y;
            }
            return point;
        }
        public override Bitmap GetBitmap()
        {
            for (int i = 0; i < bitmapData.Count; i++)
            {
                bitmapData[i].PointID++;
                if (bitmapData[i].PointID == PointDatas.Length)
                {
                    bitmapData[i].PointID = 0;
                 //   Thread.Sleep(200);
                }
                bitmapData[i].ShowOrder = PointDatas[bitmapData[i].PointID].ShowOrder;
                bitmapData[i].DstSize = new Size((int)PointDatas[bitmapData[i].PointID].Size.Width, (int)PointDatas[bitmapData[i].PointID].Size.Height);
                if (PointDatas[bitmapData[i].PointID].PointType == 0)
                {
                    bitmapData[i].NowPoint = new Point((int)PointDatas[bitmapData[i].PointID].Point.X, (int)PointDatas[bitmapData[i].PointID].Point.Y);
                }
                else
                {
                    bitmapData[i].NowPoint = new Point((int)PointDatas[bitmapData[i].PointID].Point.X - bitmapData[i].DstSize.Width, (int)PointDatas[bitmapData[i].PointID].Point.Y);
                }
            }

            bitmapData.Sort((x, y) => x.ShowOrder.CompareTo(y.ShowOrder));
            if (sourceBitmap == null)
            {
                sourceBitmap = new Bitmap(BoxWidth, BoxHeight);
            }
            var g = Graphics.FromImage(sourceBitmap);
            g.Clear(Color.Black);
            var imgAtt = new ImageAttributes();
            imgAtt.SetWrapMode(WrapMode.TileFlipXY);
            for (int i = 0; i < bitmapData.Count; i++)
            {
                g.DrawImage(bitmapData[i].bitmap, new Rectangle(bitmapData[i].NowPoint, bitmapData[i].DstSize), 0, 0, bitmapData[i].bitmap.Width, bitmapData[i].bitmap.Height, GraphicsUnit.Pixel, imgAtt);

            }
            SolidBrush brush = new SolidBrush(Color.Black);
            for (int i = 0; i < bitmapData.Count; i++)
            {
                g.DrawString(bitmapData[i].ShowOrder.ToString() + " " + bitmapData[i].PointID.ToString(), new Font("宋体", 9), brush, bitmapData[i].NowPoint);
            }
            g.Dispose();
            return sourceBitmap;
        }
    }
}
